#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <time.h>
#include <sys/time.h>
#include <sys/mount.h>
#include <cutils/sockets.h>
#include <poll.h>
#include <ctype.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <math.h>
#include <arpa/inet.h>
#include <cutils/properties.h>
#include "camera.h"
#include "platform_config.h"
#include "myjni.h"
#define UPDATE_PATH "/data/local/tmp/update.zip"
#define EXTRACT_TO "/data/local/tmp/update"
#define SYSTEM_CMD_FILE    "/data/local/tmp/update/systemCmd.txt"
int epoll_cmdfd;
volatile int flag_login = 0;
volatile int flag_newIp = 0;
volatile int threadRuning = 1;
volatile unsigned int start_deep_work = 0;
extern void *gps_state_init(void *arg);
extern int playMusic(const char *path);
extern inline int read_gps_data(stru_GPSPOINT *data);
extern int GPS_POINT_Index;
extern int GPS_POINT_Index1;
extern double ShouGeLen;
extern double LengMaxx;
extern double LengMaxy;
extern int fd_gprs;
extern int RawGpsDataIndex;
extern _GPSDATAREG   gpsdata;
extern volatile int ultra_uart_data;
extern int area_fd, priv_fd, gps_fd;
extern char iccid[PROPERTY_VALUE_MAX];
SysInf  SysInfor;
extern u8 g_flagOfStartWork;
extern u32 g_currentAdValue;
extern double g_areaInMu;
extern double g_areaOfTravel;
//函数定义区
double  cur_lat = 0, cur_lon = 0;
static void generate_zip_pack(void);
int at24c64_flags = 0;
DATA_TO_SEND data_to_send;
static int    threadSocketFd[2];
int localSocketR, localSocketW;

void sleepMsec(long long msec)
{
    struct timespec ts;
    int err; 

    ts.tv_sec = (msec / 1000);
    ts.tv_nsec = (msec % 1000) * 1000 * 1000;

    do { 
        err = nanosleep (&ts, &ts);
    } while (err < 0 && errno == EINTR);
}
void sleepUsec(long long usec)
{
    struct timespec ts;
    int err; 

    ts.tv_sec = (usec / 1000000);
    ts.tv_nsec = usec;

    do { 
        err = nanosleep (&ts, &ts);
    } while (err < 0 && errno == EINTR);
}
#define MSG_ID 0x0801
#define PICTURE_DIV 960


#define ID_UPDATE_QUERY     0x0108  //查询升级包
#define ID_UPDATE_ISSUED    0X8108  //下发升级包信息
#define ID_UPDATE_REQUEST   0x0108  //请求升级包
#define ID_UPDATE_DOWNLOAD  0X8108  //下发升级包数据

#define UPDATE_TYPE 2 //1收割机 2深松机设备

#define UPDATE_SUCCESS 0
#define UPDATE_ERROR   1
#define UPDATE_CANCEL  2
#define UPDATE_REQUEST 3
#define UPDATE_QUERY  4

struct msg_pack_info {
    unsigned short div_num;//分包总数
    unsigned short id;//分包id号,start from 1
}__attribute__((packed));

struct msg_head {
    unsigned short id;
    unsigned short prop;
    unsigned char phone_num[6];
    unsigned short serial_num;//start form 0
}__attribute__((packed));

struct  query_data {
    unsigned char type;
    unsigned char result;
}__attribute__((packed));

struct  q_result_data {
    unsigned char type;
    unsigned char vendor[5];
    unsigned char version[5];
    unsigned int package_len;
}__attribute__((packed));


struct  respond_data {
    unsigned short div_num;
    unsigned short id;
}__attribute__((packed));



struct update_query {
    struct msg_head head;
    struct query_data data;
}__attribute__((packed));

struct query_result {
    struct msg_head head;
    struct q_result_data data;
}__attribute__((packed));


struct request_result {
    struct msg_head head;
    struct msg_pack_info pack;//请求返回打包数据，所以有该项
    struct q_result_data data;
}__attribute__((packed));


static unsigned char gen_xor(unsigned char *buf, unsigned int len) {
    unsigned char xor = buf[0];
    unsigned int i;    
    for (i = 1; i < len; i++) {
        xor ^= buf[i];
    }

    return xor;
}



static unsigned int  data_checkout(unsigned char *src, unsigned int len) {
    unsigned int i =0, j = 0;
    unsigned char *dest = (unsigned char *)malloc(len);

    if (len < 1)
        return 0;
    dest[j++] = src[0];
    for (i = 1; i < len - 1; i++) {
        if (src[i] == 0x7d) {
            if (src[i+1] == 0x01) {
                dest[j++] = 0x7d;
                i++;
            } else if (src[i+1] == 0x02) {
                dest[j++] = 0x7e;
                i++;
            }
        } else {
            dest[j++] = src[i]; 
        }
    }
    dest[j++] = src[len-1];
    memcpy(src, dest, j);
    free(dest);

    return j;
}
#define QUERY_ERR -1
#define QUERY_NEW_VERSION 0
#define QUERY_NOTHING 1
static int updateQuery(unsigned int *V) {
    unsigned char data[128];
    int i, len, t_len = 0;
    struct update_query query;
    unsigned short serial_num = 0;
    unsigned char *sendBuf = data;

    sendBuf[0] = 0x7e;//数据头标识
    sendBuf++;

    query.head.id = htons(ID_UPDATE_QUERY);
    query.head.prop = htons(sizeof(struct query_data));
    char *serial = SysInfor.LocalPhoneNum1; 
    for(i=0; i<6; i++)
    {
        char format[3];
        strncpy(format, serial, 2);
        format[2] = 0;
        int num = atoi(format);
        serial += 2;
        query.head.phone_num[i] = (num/10)*16+num%10;
    }
    query.head.serial_num = htons(serial_num);
    //query.head.pack.div_num = htons(0);
    //query.head.pack.id = htons(0);
    query.data.type = UPDATE_TYPE;
    query.data.result = UPDATE_QUERY;

    memcpy(sendBuf, &query, sizeof(query));
    sendBuf[sizeof(query)] = gen_xor(sendBuf, sizeof(query));//校验位
    sendBuf[sizeof(query) + 1] = 0x7e;//数据尾标识
    len = 0;
    i = 0;
    LOGE("升级查询 发送内容%dbyte:", sizeof(query)+3);
    len = GPRSDataSend((char *)data, sizeof(query) + 3, 10000000, 127, 0);
    if (len <= 0) {
        LOGE("发送升级查询失败");
        return QUERY_ERR;
    }
    LOGE("查询升级包返回:%d", len);
    if (len < 2)
        return QUERY_ERR;
    HEX_Print((char *)data, len);
    len = data_checkout((unsigned char *)data, (unsigned int)len);
    LOGE("查询转义:%d", len);
    if (gen_xor((unsigned char *)data + 1, len-3) != data[len-2]) {
        LOGE("校验失败");
        return QUERY_ERR;
    }
    struct query_result q_result;
    char *p = (char *)data;
    p++;
    memcpy(&q_result, p, sizeof(q_result));
    q_result.head.serial_num = ntohs(q_result.head.serial_num);
    q_result.data.package_len = ntohl(q_result.data.package_len);
    LOGE("流水号:%d", q_result.head.serial_num);
    LOGE("厂商号:");
    CHAR_Print((char *)q_result.data.vendor, sizeof(q_result.data.vendor));
    LOGE("版本号:");
    CHAR_Print((char *)q_result.data.version, sizeof(q_result.data.version));
    LOGE("数据包长度:%d", q_result.data.package_len);
    char version[6];
    memset(version, 0, sizeof(version));
    memcpy(version, q_result.data.version + 1, 4);
    unsigned int ver = (unsigned int)(atof(version)*100);
    *V = (unsigned int)ver;
    if (ver > SysInfor.version) {
        LOGE("检测到新版本：%d,原版本:%d", ver, SysInfor.version);
        return QUERY_NEW_VERSION;
    }
    LOGE("当前已是最新版本");
    return QUERY_NOTHING;
}

static int update_err_count = 0; 
struct update_package_info {
    char *data;
    unsigned int len;
};
extern int socket_cli;
static int updateRequest(struct update_package_info *package1, int *packageNum) {
    unsigned char *sendBuf;
    unsigned int i, t_len = 0;
    unsigned long len;
    struct update_query query;
    unsigned short serial_num = 0;
    struct query_result q_result;
    struct timeval tv1, tv2;
    unsigned char dataSend[128];
    //app_info info;
    //info.bit = BIT_APP_UPDATE_PROGRESS;
    //info.data = -1;
    sendBuf = dataSend;
    sendBuf[0] = 0x7e;//数据头标识
    sendBuf++;

    gettimeofday(&tv1, (struct timezone *) NULL);
    query.head.id = htons(ID_UPDATE_QUERY);
    query.head.prop = htons(sizeof(struct query_data));
    char *serial = SysInfor.LocalPhoneNum1; 
    for(i=0; i<6; i++)
    {
        char format[3];
        strncpy(format, serial, 2);
        format[2] = 0;
        int num = atoi(format);
        serial += 2;
        query.head.phone_num[i] = (num/10)*16+num%10;
    }
    query.head.serial_num = htons(serial_num);
    //query.head.pack.div_num = htons(0);
    //query.head.pack.id = htons(0);
    query.data.type = UPDATE_TYPE;
    query.data.result = UPDATE_REQUEST;

    memcpy(sendBuf, &query, sizeof(query));
    sendBuf[sizeof(query)] = gen_xor(sendBuf, sizeof(query));//校验位
    sendBuf[sizeof(query) + 1] = 0x7e;//数据尾标识
    len = 0;
    i = 0;
    LOGE("升级请求 发送内容%dbyte:", sizeof(query)+3);
    HEX_Print((char *)dataSend, sizeof(query) + 3);
    int ret = GPRSDataSend((char *)dataSend, sizeof(query) + 3, 0, 127, 0);
    //if (ret <= 0) {
   //     LOGE("发送升级请求失败");
    //    return -1;
   // }
    len = 0;
    i = 0;
    char *pack_data = malloc(1024*1024*5);
    int count = 0;
    int head_count = 0;
    //int read_flags = 1;
    int timeout_count = 0;
    struct request_result result;
    unsigned int head_len = sizeof(struct request_result);
    int flags = 1;
#if 0
    while (1) {
        nevents = epoll_wait(epoll_uartfd, &events, 1, 10000);
        if ((nevents > 0) && ((events.events & EPOLLIN) != 0)) {
            count = read(fd_gprs, pack_data + len, 2000);
            if (count > 0) {
                len += count;
                if (flags && (update_err_count==0) && (len>head_len)) {
                    flags = 0;
                    memcpy(&result, pack_data + 1, head_len);
                    result.pack.div_num = ntohs(result.pack.div_num);
                    result.pack.id = ntohs(result.pack.id);
                    package_size = 2*1024*1024;//result.pack.div_num*1042;
                    //LOGE("package_size=%d", package_size);
                }
            }
        } else {
            LOGE("uart timeout");
            break;
        }
    }
#endif
    while (socket_cli != -1) {
        fd_set readfds;
        struct timeval tv;
        FD_ZERO(&readfds);
        FD_SET(socket_cli, &readfds);
        tv.tv_sec = 10;
        tv.tv_usec = 0;
        ret = select(socket_cli + 1, &readfds, NULL, NULL, &tv); //阻塞,err:0 timeout err:-1 错误见errno
        if (ret > 0 && FD_ISSET(socket_cli, &readfds)) {
            if (len >= 1024*1023*5)
                break;
            count = read(socket_cli, pack_data + len, 1024);
            if (count > 0) {
                len += count;
                LOGE("download total=%lu, count =%d", len, count);
                if (flags && (len>head_len)) {
                    flags = 0;
                    memcpy(&result, pack_data + 1, head_len);
                    result.pack.div_num = ntohs(result.pack.div_num);
                    result.pack.id = ntohs(result.pack.id);
                }

            } else {
                LOGE("socket recv unknown err[%s]", strerror(errno));
                break;
            }
        } else {
            LOGE("ret=%d, select timeout err=%s", ret, strerror(errno));
            if (errno == ECONNRESET || errno == EPIPE) {
                socket_cli = -1;
            }
            break;
        }
    }

    unsigned int j = 0;
    char *p = pack_data; 
    int error_count = 0, success_count = 0;
    for (i = 0; i < len; i++) {
        p[j++] = pack_data[i];
        if ((pack_data[i] == 0x7e) && (++head_count % 2 == 0)) {
            count = data_checkout((unsigned char *)p, j);
            unsigned char xor = gen_xor((unsigned char *)p + 1, count - 3); 
            if ( xor != *(p + count - 2)) {
                LOGE("校验失败 id=%d, len=%d", head_count/2, count);
                error_count++;
            } else {
                memcpy(&result, p + 1, head_len);
                result.pack.div_num = ntohs(result.pack.div_num);
                result.pack.id = ntohs(result.pack.id);
                if (xor == *(p + 1 + head_len + result.data.package_len)) {//这里还要校验一次，有可能数据中夹带有00等其他干扰数据
                    memcpy(package1[result.pack.id-1].data, p, count);
                    *packageNum = result.pack.div_num;
                    package1[result.pack.id-1].len = count;
                    success_count++;
                  //  LOGE("校验成功");
                } else {
                    LOGE("二次校验失败 id=%d", result.pack.id);
                    error_count++;
                }
                //LOGE("head_len=%d, count=%d package_len=%d", head_len, count, result.data.package_len);
            }
            j = 0;
        }
    }
    gettimeofday(&tv2, (struct timezone *) NULL);
    LOGE("下载完成，校验错误包:%d个, 耗时:%lu分%lu秒", error_count, SEC_DIFF(tv1, tv2)/60, SEC_DIFF(tv1, tv2)%60);
    free(pack_data);

    return error_count;
}

static int extract_update_package(void) {
    system("mkdir /data/local/tmp/update");
    if (unzip(UPDATE_PATH, NULL, NULL, EXTRACT_TO)) {
        LOGE("解压升级包失败");
        return -1; 
    }   
    system("chmod -R 777 /data/local/tmp/update");
    sync();
    char md5Val[33];
    char md5Buf[256];
    int md5CheckResult = 0;

    int ret = Compute_file_md5("/data/local/tmp/update/uartService", md5Val);
    if (ret != 0) {
        LOGE("compute MD5 fail");
        return -1;
    }
    LOGE("update packge MD5:%s", md5Val);
    FILE *fp = fopen("/data/local/tmp/update/MD5.txt", "r");
    if (!fp) {
        LOGE("open MD5.txt fail[%s]", strerror(errno));
        return -1;
    }
    while (fgets(md5Buf, sizeof(md5Buf), fp)) {
        if (strstr(md5Buf, md5Val)) {
            LOGE("MD5 check ok");
            md5CheckResult = 1;
            break;
        }
    }
    fclose(fp);
    if (md5CheckResult == 0)
        return -1;
    write_log_to_sdcard("MD5校验通过"); 
    remount_system(MS_REMOUNT);
    system("rm /system/bin/uartService; cp /data/local/tmp/update/uartService /system/bin/;chmod 755 /system/bin/uartService");
    if (access("/data/local/tmp/update/SystemCmd.txt", F_OK) == 0) {
        systemCmd("/data/local/tmp/update/SystemCmd.txt");
    }
    system("busybox rm /data/local/tmp/update* -rf; sync");
    write_log_to_sdcard("升级成功，重启");
    system("reboot");
    return 0;
}


static void checkOfflineData() {
    u8 gprsSendIsSuccess;

    gprsSendIsSuccess = sendOfflineArea();
    if (gprsSendIsSuccess == AREA_DATA_SUCCESS) {
        update_area_data_tail();
        LOGE("Send area and depth data success");
        write_log_to_sdcard("发送离线面积成功");
    } else if (gprsSendIsSuccess == AREA_DATA_ERROR) {
        LOGE("Send area and depth data fail, retry again!");
        write_log_to_sdcard("发送离线面积失败");
    } else if (gprsSendIsSuccess == AREA_DATA_SKIP) {
        update_area_data_tail();
    }
}


//补传油耗，上报位置信息，心跳，终端注册鉴权
void *SupplementOilAndReportLocation (void * arg) {
    struct timeval g_tv = {.tv_sec = 0, .tv_usec = 0}, 
                   offline_tv = {.tv_sec = 0, .tv_usec = 0}, area_tv = {.tv_sec = 0, .tv_usec = 0}, 
                   locat_tv = {.tv_sec = 0, .tv_usec = 0}, plus_tv = {.tv_sec = 0, .tv_usec = 0}, picture_tv = {.tv_sec = 0, .tv_usec = 0};
    int i;
    int msec, ret;
    int success_count = 0;
    int start_deep_work_temp = 0;
    unsigned long gps_auto_calc_state = 0, start_deep_work_state = 0;

    while (socket_init() == -ENETUNREACH) {
        sleepMsec(1000);
    }
    while(threadRuning) {
        gettimeofday(&g_tv, (struct timezone *) NULL);
        if(0 == flag_login) {//系统未注册
            if (flag_newIp) {
                flag_newIp = 0;
                socket_init();
            }
            if(abs(SEC_DIFF(g_tv, offline_tv)) >= 10) {
                LOGE("offline, duration:%ld seconds", SEC_DIFF(g_tv, offline_tv));
                offline_tv = g_tv;
                LoginAndAuthentication();
            }
        } else {   //在线
            if (abs(SEC_DIFF(g_tv, area_tv)) >= 3) {
                area_tv = g_tv;
                checkOfflineData(); 
            }

            if(abs(SEC_DIFF(g_tv, locat_tv)) >= 6) {
                locat_tv = g_tv;
                if(report_locat(g_flagOfStartWork, g_currentAdValue) == 1) {//这里要上传的单位是cm,加5是为了4舍5入AA
                    LOGE("Send loaction success!");
                } else {
                    LOGE("Send loaction error!");
                }

            }

            if(abs(SEC_DIFF(g_tv, plus_tv)) >= 30) {
                plus_tv = g_tv;
                if (1 == plus())
                    LOGE("Send plus success");
                else
                    LOGE("Send plus fail!");
            }
        }
        sleepMsec(10);
    }
    LOGE("线程%s退出", __func__);
    return NULL;
}

static pthread_t wifi_ap_thread;
#define SOCKET_NAME "uartService"
void *read_para(void * arg)
{

    struct sockaddr addr;
    socklen_t alen;
    int lsocket, s;
    char buf[256] = {0};
    char info[256];
    LOGE("read para thread create");
    
    lsocket = android_get_control_socket(SOCKET_NAME);
    if (lsocket < 0) {
        LOGE("Failed to get socket from environment: %s\n", strerror(errno));
        return NULL;
    }
    if (listen(lsocket, 5)) {
        LOGE("Listen on socket failed: %s\n", strerror(errno));
        return NULL;
    }

    for (;;) {
        alen = sizeof(addr);
        LOGE("socket ready...");
        memset(info, 0, sizeof(info));
        sprintf(info, "%s:%d;%s;%s", SysInfor.IP, SysInfor.port, SysInfor.terminalID, SysInfor.CarNumber_utf8);
        property_set("rw.uartservice.mms.info", info);
        s = accept(lsocket, &addr, &alen);
        if (s < 0) {
            LOGE("Accept failed: %s\n", strerror(errno));
            sleepMsec(1000);
            continue;
        } else {
            struct pollfd fds;
            int nr; 
            int check_count;
            bzero(buf, sizeof(buf));
            fds.fd = s; 
            fds.events = POLLIN;
            fds.revents = 0;
            nr = poll(&fds, 1, 1000);
            LOGE("poll in");
            read(s, buf, sizeof(buf));
            if (strncmp("sd_para", buf, 7) == 0) {
                check_count = 0;
                while (check_count++ < 20) {
                    sleepMsec(100);
                    if(checkExFile() > 0)
                        break;
                }
            } else if (strncmp("gsm_ccid", buf, 8) == 0) {
                LOGE("%s", buf);
                memset(iccid, 0, sizeof(iccid));
                snprintf(iccid, sizeof(iccid), "%s", buf + 9);
            } else if (strncmp("mms_para", buf, 8) == 0) {
                //LOGE("%s", buf);
                split(buf + 9);
                at24c64Write(priv_fd, SYSINFO_SET, (char *)&SysInfor, SysInfLength);
            } else if (strncmp("ap_thread", buf, 9) == 0) {
                pthread_create(&wifi_ap_thread, NULL, listenWifiAp, (void *)s);
            }
        }
    }

    return NULL;
}

static pthread_cond_t s_commandcond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t s_commandmutex = PTHREAD_MUTEX_INITIALIZER;

static void music_wakeup_signal() {
    pthread_mutex_lock(&s_commandmutex);
    pthread_cond_signal(&s_commandcond);
    pthread_mutex_unlock(&s_commandmutex);
}

static void setTimespecRelative(struct timespec *p_ts, long long msec)
{
    struct timeval tv;

    gettimeofday(&tv, (struct timezone *) NULL);

    /* what's really funny about this is that I know
       pthread_cond_timedwait just turns around and makes this
       a relative time again */
    p_ts->tv_sec = tv.tv_sec + (msec / 1000);
    p_ts->tv_nsec = (tv.tv_usec + (msec % 1000) * 1000L ) * 1000L;
}

void *thread_play_music(void * arg) {
    struct timespec ts;
    int err;

    for (;;) {
        setTimespecRelative(&ts, 10000000);
        pthread_mutex_lock(&s_commandmutex);
        err = pthread_cond_timedwait(&s_commandcond, &s_commandmutex, &ts);
        pthread_mutex_unlock(&s_commandmutex);
        if (err == ETIMEDOUT) {//休眠等待超时
            continue;
        } else {
            LOGE("thread_play_music---play music");
            playMusic("/system/media/yaoliang.wav");
        }
    }
    return NULL;
}

extern volatile int gps_state;
extern int adc_error;
unsigned int g_led_display = 0;
int g_led_display_counter = 0;
int g_power_del_counter = 0;
static void *ledServer(void * arg) {
    int system_led = 0;
    unsigned int display;
    unsigned int play_music_counter = 0;

    sleepMsec(5*1000);
    while (1) {
        display = g_led_display; 
        if (g_led_display_counter && g_led_display_counter++ > 10)
            g_led_display_counter = 0;

        if (!g_led_display_counter && pesticidesLiter_button) {//计算面积显示5秒亩数，然后判断如果喷药则显示ad值百分比
            display = MIN(1000, g_currentAdValue*1000/3900); 
        }
		//LOGE("ledServer---display:%u", display);
        write_led(display, system_led, gps_state, flag_login, g_currentAdValue < SysInfor.str_linearList[4].adValue/10);
        system_led = !system_led;
        
		if ((g_currentAdValue < 390))//药水小于10%，每10秒播放一次语音提示
		{
			play_music_counter++;
			if(play_music_counter<101 && (play_music_counter % 20 )== 0 && pesticidesLiter_button ==1 )
				{
					LOGE("ledServer---play music");
					//music_wakeup_signal();
				}
		}
		else
		{
			play_music_counter = 0;
		}

		//电源断电延时
		if (g_power_del_counter && g_power_del_counter++ > 10)
		{
			LOGE("断开电源5秒结束工作");
			int work = STOP_WORK;
			write(localSocketW, &work, sizeof(work));
			g_power_del_counter = 0;
		}

        sleepMsec(500);
    }
    return NULL;

}

static void generate_zip_pack(void) {
    char TARGET_PATH[128];
    int argc = 9;
    char *argv[9] = {"minizip", "-o", "-0", "-9", "-p", "3699", "-j", TARGET_PATH, GPS_DATA_LOG_PATH};
    FILE *fp; 
    long len = 0;
    long max_len = 50*1024*1024; 
    
    sync();
    fp = fopen(GPS_DATA_LOG_PATH, "r");
    if (fp) {
        fseek(fp, 0L, SEEK_END);
        len = ftell(fp);
        LOGE("gpsData len=%ld", len);
        fclose(fp);
    }
    if (len > max_len)
        sprintf(TARGET_PATH, "/storage/sdcard1/%sbak.zip", SysInfor.terminalID);
    else
        sprintf(TARGET_PATH, "/storage/sdcard1/%s.zip", SysInfor.terminalID);

    fp = fopen(TARGET_PATH, "wb");
    if (fp) {
        fclose(fp);
        minizip(argc, argv);
        LOGE("写入压缩文件%s", TARGET_PATH);
        if (len > max_len)//确认外部sd卡存在的情况下才删除源文件
            remove("data/local/tmp/gpsData.txt");
    }
    sync();
}


static pthread_t ntid[6];
void os_sys_init() {
    int ret;
    
    ret = pthread_create(&ntid[0], NULL, SupplementOilAndReportLocation, NULL);//注册，鉴权，心跳，位置信息，测亩信息
    ret = pthread_create(&ntid[1], NULL, readAdcUart, NULL);
    ret = pthread_create(&ntid[2], NULL, ledServer, NULL);
    ret = pthread_create(&ntid[3], NULL, read_para, NULL);//读取SDCARD/USB参数
    ret = pthread_create(&ntid[4], NULL, thread_play_music, NULL);
}

static void handle_pipe(int sig) {
    LOGE("捕获到内核发送网络异常信号");
}

int main (void) {
    int ret;
    pthread_t thread_gps;
    void *result;
    
    init_log_buf();
    INIT_LIST_HEAD(&data_to_send.head);
    open_led();
    if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, threadSocketFd ) < 0 ) { 
        printf("could not create thread control socket pair: %s\n", strerror(errno));
    }   
    localSocketR = threadSocketFd[1];
    localSocketW = threadSocketFd[0];
    write_log_to_sdcard("\r\n\r\n\r\n\r\n系统开机");
    openAdcUart("/dev/ttyHSL1", 0);
    register_local_socket(localSocketR);
    area_fd = block_init(AREA_PATH, AREA_OFFLINE_LEN);
    priv_fd = block_init(PRIVATE_PAR, 512);
    gps_fd = block_init(GPS_DATA_PATH, GPS_MAX_DATA*sizeof(stru_GPSPOINT));
    
    memset(gpsdata.gps_data, 0, sizeof(gpsdata.gps_data));
    strcpy((char *)gpsdata.gps_data, GPS_DATA_BUF); //fix data parser NULL bug
    device_init();
    write_led(19, 0, 0, 0, 0);//显示版本号，显示为第一个参数/10

    ret = pthread_create(&thread_gps, NULL, gps_state_init, NULL);

    struct sigaction action;
    action.sa_handler = handle_pipe;
    sigemptyset(&action.sa_mask);
    action.sa_flags = 0;
    sigaction(SIGPIPE, &action, NULL);
    GetAuthenticationCode();//从存储芯片中提取鉴权码

    os_sys_init();
    adcTimer();
    power_detect_signal();
    pthread_join(thread_gps, &result);
    closeAdcUart();
    at24c64_close();
    close_power_detect();
    free_log_buf();
    close_led();

    return 0;
}

